package com.aizuda.boot.modules.business.job;

import com.aizuda.boot.modules.business.contract.entity.ContractEntity;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldEntity;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldValueEntity;
import com.aizuda.boot.modules.common.constant.enums.ContractStatusEnum;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldValueMapper;
import com.aizuda.boot.modules.business.contract.service.ContractFieldService;
import com.aizuda.boot.modules.business.contract.service.ContractService;
import com.aizuda.boot.modules.business.filling.domain.entity.ContractFilingTypeEntity;
import com.aizuda.boot.modules.business.filling.service.ContractFilingService;
import com.aizuda.boot.modules.business.filling.service.ContractFilingTypeService;
import com.aizuda.boot.modules.common.MessageEvent;
import com.aizuda.boot.modules.common.constant.enums.SystemFieldsEnum;
import com.aizuda.boot.modules.system.entity.SysUserDepartment;
import com.aizuda.boot.modules.system.entity.enums.BusinessType;
import com.aizuda.boot.modules.system.service.ISysUserDepartmentService;
import com.aizuda.boot.modules.system.service.ISysUserRoleService;
import com.aizuda.bpm.engine.FlowLongEngine;
import com.aizuda.bpm.engine.entity.FlwTask;
import com.aizuda.bpm.engine.entity.FlwTaskActor;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xxl.job.core.handler.annotation.XxlJob;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author sangyirong
 * @ClassName JobDemo
 * @Version 1.0
 * @Date 2025/7/9 12:01
 */
@Slf4j
@Component
public class FilingJob {

    @Resource
    private ContractFilingService contractFilingService;

    @Resource
    private ContractFilingTypeService contractFilingTypeService;

    @Resource
    private ContractFieldValueMapper contractFieldValueMapper;

    @Resource
    private ContractService contractService;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    private ContractFieldService contractFieldService;

    @Resource
    private FlowLongEngine flowLongEngine;

    @Resource
    private ISysUserRoleService sysUserRoleService;

    @Resource
    private ISysUserDepartmentService sysUserDepartmentService;

    @XxlJob("sendFillingMessageHandler")
    public void sendFilingMessage(){
        log.info("开始执行归档提醒任务");
        
        contractFilingService.list().forEach(filing -> {
            Integer reminderRule = filing.getReminderRule();
            if (reminderRule == null || reminderRule <= 0) {
                log.debug("归档规则 {} 的提醒规则为空或无效，跳过", filing.getId());
                return;
            }
            
            // 获取归档规则对应的合同类型ID列表
            List<Integer> typeIds = contractFilingTypeService.list(Wrappers.<ContractFilingTypeEntity>lambdaQuery()
                    .eq(ContractFilingTypeEntity::getFilingId, filing.getId())
                    .select(ContractFilingTypeEntity::getContractTypeId))
                    .stream().map(ContractFilingTypeEntity::getContractTypeId).collect(Collectors.toList());
            
            if (typeIds.isEmpty()) {
                log.debug("归档规则 {} 没有关联的合同类型，跳过", filing.getId());
                return;
            }

            // 获取合类型同字段id
            ContractFieldEntity contractTypeField = contractFieldService.getOne(Wrappers.<ContractFieldEntity>lambdaQuery()
                    .eq(ContractFieldEntity::getCode, SystemFieldsEnum.CONTRACT_TYPE.getCode()));


            // 根据合同类型查找对应的合同ID列表
            List<Integer> contractIds = contractFieldValueMapper.selectList(Wrappers.<ContractFieldValueEntity>lambdaQuery()
                            .eq(ContractFieldValueEntity::getFieldId, contractTypeField.getId()) // 合同类型字段ID为25
                            .in(ContractFieldValueEntity::getFieldValue, typeIds)
                            .select(ContractFieldValueEntity::getContractId))
                    .stream().map(ContractFieldValueEntity::getContractId).collect(Collectors.toList());
            
            if (contractIds.isEmpty()) {
                log.debug("归档规则 {} 没有找到相关合同，跳过", filing.getId());
                return;
            }
            
            // 查找状态为归档中且超过提醒时间的合同
            List<ContractEntity> overdueContracts = contractService.list(Wrappers.<ContractEntity>lambdaQuery()
                    .in(ContractEntity::getId, contractIds)
                    .eq(ContractEntity::getCurrentStatus, ContractStatusEnum.SEALED.getCode()));
            
            // 过滤出超过提醒时间的合同
            LocalDateTime now = LocalDateTime.now();
            List<ContractEntity> contractsToRemind = overdueContracts.stream()
                    .filter(contract -> {
                        if (contract.getUpdatedAt() == null) {
                            return false;
                        }
                        // 计算进入归档状态的天数
                        long daysSinceUpdate = ChronoUnit.DAYS.between(contract.getUpdatedAt(), now);
                        return daysSinceUpdate >= reminderRule;
                    })
                    .collect(Collectors.toList());
            
            // 发送提醒消息
            contractsToRemind.forEach(contract -> {
                sendArchivingReminder(contract, reminderRule);
            });
            
            log.info("归档规则 {} 处理完成，找到 {} 个超时合同", filing.getRuleName(), contractsToRemind.size());
        });
        
        log.info("归档提醒任务执行完成");
    }

    /**
     * 发送归档提醒消息
     * @param contract 合同实体
     * @param reminderDays 提醒天数
     */
    private void sendArchivingReminder(ContractEntity contract, Integer reminderDays) {
        try {
            List<Long> sendUser = new ArrayList<>();
            // 获取合同经办人ID（字段ID为28）
            List<Long> handlerIds = getContractHandlers(contract.getId());
            
            if (!handlerIds.isEmpty()) {
                sendUser.addAll(handlerIds);
            }

            List<Long> currentNodeHandlerIds = getCurrentNodeHandlerIds(contract.getId());
            if (!CollectionUtils.isEmpty(currentNodeHandlerIds)){
                sendUser.addAll(currentNodeHandlerIds);
            }
            
            if (CollectionUtils.isEmpty(sendUser)){
                log.warn("合同 {} 未找到需要通知的人员", contract.getId());
                return;
            }

            ContractFieldEntity field = contractFieldService.getOne(Wrappers.<ContractFieldEntity>lambdaQuery()
                    .eq(ContractFieldEntity::getCode, SystemFieldsEnum.CONTRACT_NAME.getCode())
                    .last("limit 1"));

            // 获取合同名称
            String contractName = getContractFieldValue(contract.getId(), field.getId()); // 合同名称字段ID为5
            if (contractName == null) {
                contractName = "未知合同";
            }
            
            // 构建消息内容
            String title = "合同归档提醒";
            String content = String.format("合同【%s】已进入归档状态超过%d天，请尽快完成归档操作。",
                    contractName, reminderDays);
            
            // 发送消息事件
            MessageEvent messageEvent = new MessageEvent();
            messageEvent.setTitle(title);
            messageEvent.setContent(content);
            messageEvent.setCreateId(0L);
            messageEvent.setCreateBy("系统");
            messageEvent.setCategory(2); // 2表示待办消息
            messageEvent.setBusinessId(contract.getId().longValue());
            messageEvent.setBusinessType(BusinessType.filing.name());

            messageEvent.setUserIds(sendUser);
            
            applicationEventPublisher.publishEvent(messageEvent);
            
            log.info("已发送归档提醒消息：合同ID={}, 经办人={}, 超时天数={}", 
                    contract.getId(), sendUser, reminderDays);
            
        } catch (Exception e) {
            log.error("发送归档提醒消息失败，合同ID: {}", contract.getId(), e);
        }
    }

    private List<Long> getCurrentNodeHandlerIds(Integer contractId) {
        try {
            // 查询合同信息获取审批实例ID
            ContractEntity contract = contractService.getById(contractId);
            if (contract == null || contract.getApprovalInstanceId() == null) {
                log.debug("合同 {} 没有审批实例ID", contractId);
                return new ArrayList<>();
            }

            // 获取当前活跃任务
            List<FlwTask> activeTasks = flowLongEngine.queryService().getTasksByInstanceId(contract.getApprovalInstanceId());
            if (activeTasks == null || activeTasks.isEmpty()) {
                log.debug("合同 {} 没有活跃的审批任务", contractId);
                return new ArrayList<>();
            }

            List<Long> handlerIds = new ArrayList<>();

            // 遍历所有活跃任务，获取任务执行人
            for (FlwTask task : activeTasks) {
                List<FlwTaskActor> taskActors = flowLongEngine.queryService().getTaskActorsByTaskId(task.getId());
                if (taskActors != null) {
                    for (FlwTaskActor actor : taskActors) {
                        // actor_type = 0 表示用户类型
                        if (actor.getActorType() == 0) {
                            try {
                                handlerIds.add(Long.parseLong(actor.getActorId()));
                            } catch (NumberFormatException e) {
                                log.warn("解析任务执行人ID失败，任务ID: {}, 执行人ID: {}", task.getId(), actor.getActorId(), e);
                            }
                        }
                        // 角色类型
                        else if (actor.getActorType() == 1) {
                            try {
                                Long roleId = Long.parseLong(actor.getActorId());
                                List<Long> userIds = sysUserRoleService.listUserIdsByRoleIds(List.of(roleId));
                                handlerIds.addAll(userIds);
                            } catch (NumberFormatException e) {
                                log.warn("解析角色ID失败，任务ID: {}, 角色ID: {}", task.getId(), actor.getActorId(), e);
                            }
                        }
                        // 部门类型
                        else if (actor.getActorType() == 2) {
                            try {
                                Long deptId = Long.parseLong(actor.getActorId());
                                List<Long> userIds = sysUserDepartmentService.list(Wrappers.<SysUserDepartment>lambdaQuery()
                                        .eq(SysUserDepartment::getDepartmentId, deptId)
                                        .select(SysUserDepartment::getUserId))
                                        .stream().map(SysUserDepartment::getUserId).collect(Collectors.toList());
                                handlerIds.addAll(userIds);
                            } catch (NumberFormatException e) {
                                log.warn("解析部门ID失败，任务ID: {}, 部门ID: {}", task.getId(), actor.getActorId(), e);
                            }
                        }
                    }
                }
            }

            // 去重
            return handlerIds.stream().distinct().collect(Collectors.toList());

        } catch (Exception e) {
            log.error("获取合同当前节点执行人失败，合同ID: {}", contractId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取合同经办人ID列表
     * @param contractId 合同ID
     * @return 经办人ID列表
     */
    private List<Long> getContractHandlers(Integer contractId) {
        ContractFieldEntity field = contractFieldService.getOne(Wrappers.<ContractFieldEntity>lambdaQuery()
                .eq(ContractFieldEntity::getCode, SystemFieldsEnum.CONTRACT_HANDLER.getCode())
                .last("limit 1"));
        String handlerValue = getContractFieldValue(contractId, field.getId()); // 合同经办人字段ID为28
        List<Long> handlerIds = new ArrayList<>();
        
        if (handlerValue != null && !handlerValue.trim().isEmpty()) {
            try {
                // 支持多个经办人，用逗号分隔
                String[] handlerStrings = handlerValue.split(",");
                for (String handlerString : handlerStrings) {
                    handlerIds.add(Long.parseLong(handlerString.trim()));
                }
            } catch (NumberFormatException e) {
                log.warn("解析合同经办人ID失败，合同ID: {}, 经办人值: {}", contractId, handlerValue, e);
            }
        }
        
        return handlerIds;
    }
    
    /**
     * 获取合同字段值
     * @param contractId 合同ID
     * @param fieldId 字段ID
     * @return 字段值
     */
    private String getContractFieldValue(Integer contractId, Long fieldId) {
        List<ContractFieldValueEntity> fieldValues = contractFieldValueMapper.selectList(
                Wrappers.<ContractFieldValueEntity>lambdaQuery()
                        .eq(ContractFieldValueEntity::getContractId, contractId)
                        .eq(ContractFieldValueEntity::getFieldId, fieldId)
                        .select(ContractFieldValueEntity::getFieldValue)
        );
        
        return fieldValues.isEmpty() ? null : fieldValues.get(0).getFieldValue();
    }
}
